package com.dylan.历史.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cglib.beans.BeanCopier;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: ankang
 * @Date: 2019/2/14 14:52
 * @Description:
 */
public class BeanUtils {

    // 创建BeanCopier实例的过程比较耗时，缓存之
    private static Map<String, BeanCopier> beanCopierCache = new ConcurrentHashMap<>();
    private static final String KEY_SEPARATOR = "->";

    /**
     * 类属性拷贝
     * 只拷贝名称及类型相同的属性
     * @param source 原始对象
     * @param target 目标对象
     */
    public static void copyFields(Object source, Object target) {
        if (source == null) {
            return;
        }
        String beanCopierCacheKey = source.getClass().getCanonicalName() + KEY_SEPARATOR + target.getClass().getCanonicalName();
        BeanCopier beanCopier;
        if (!beanCopierCache.containsKey(beanCopierCacheKey)) {
            beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
        } else {
            beanCopier = beanCopierCache.get(beanCopierCacheKey);
        }
        beanCopier.copy(source, target, null);
    }

    /**
     * bean 转为 map
     * @param bean 原始Bean
     * @return Map对象
     */
    public static Map<String, Object> beanToMap(Object bean) {
        if (bean == null) {
            return null;
        }
        try {
            Map<String, Object> rs = new HashMap<>();
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                String key = propertyDescriptor.getName();
                if ("class".equals(key)) {
                    continue;
                }
                Method reader = propertyDescriptor.getReadMethod();
                if (reader != null) {
                    Object value = reader.invoke(bean);
                    if (value != null) {
                        rs.put(key, value);
                    }
                }
            }
            return rs;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * map 转为 bean
     * @param map 原始Map
     * @param clazz 目标Bean类型
     * @return 目标Bean对象
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
        String json = JSON.toJSONString(map);
        return JSONObject.parseObject(json, clazz);
    }

}
